﻿
#include "const.h"
#include "curve.h"


//IMPLEMENT_DYNAMIC_CLASS(chart, wxWindow)
BEGIN_EVENT_TABLE(chart, wxWindow)

	// catch paint events
	EVT_PAINT(chart::paint)
	EVT_SIZE(chart::onSizeEvt)
END_EVENT_TABLE()

chart::chart(wxWindow* parent,int id)
: wxWindow(parent,id)
{
	buf.Create(2000,2000);
	title=wxT("");
	xlabel=wxT("");ylabel=wxT("");
	virRed.reserve(20000);
	virBlue.reserve(20000);
	this->clearVir();
	this->SetBackgroundStyle(wxBG_STYLE_CUSTOM);
	//初始化
	busy=false;
	this->clearAll();
}


chart::~chart(void)
{
}
void chart::paint(wxPaintEvent & WXUNUSED(evt))
{
	wxPaintDC dc(this);
	//双缓冲
	wxSize sz=this->GetSize();
	int ww=sz.GetWidth(),hh=sz.GetHeight();
	buf.Create(ww,hh);

	wxMemoryDC mdc;
	mdc.SelectObject(buf);
	realDraw(mdc);
	mdc.SelectObject(wxNullBitmap);


	dc.DrawBitmap(buf.GetSubBitmap(wxRect(0,0,ww,hh)),0,0);
}

void chart::addred(double x,double y)
{

	//更新最大最小值
	if(red.getSize()==0&&blue.getSize()==0)
	{
		maxx=minx=x; 
		maxy=miny=y;
		red.add(x,y);
		refreshAll(); 
		return;
	}
	red.add(x,y);
	if(minx>x)
	{
		minx=x;
	}
	if(maxx<x)
	{
		maxx=x;
	}
	if(miny>y)
	{
		miny=y;
	}
	if( maxy<y)
	{
		maxy=y;
	}
	refreshAll();
}
void chart::addblue(double x,double y)
{
	if(blue.getSize()==0&&red.getSize()==0)
	{
		maxx=minx=x;  
		maxy=miny=y;
		blue.add(x,y);
		refreshAll(); 
		return;
	}
	blue.add(x,y);
	if(minx>x)
	{
		minx=x;
	}
	if(maxx<x)
	{
		maxx=x;
	}
	if(miny>y)
	{
		miny=y;
	}
	if( maxy<y)
	{
		maxy=y;
	}

	refreshAll();
}

void chart::clearAll()
{
	red.clear();blue.clear();
	minx=maxx=miny=maxy=0;
	clearVir();


}
void chart::setTitle(const wxString&t)
{          
	title=t;this->Refresh();
}
void chart::setXLabel(const wxString&t)
{                
	xlabel=t;this->Refresh();
}
void chart::setYLabel(const wxString&t)
{                
	ylabel=t;this->Refresh();
}
//自动绘制范围,默认关
void chart::setAuto(bool a)
{
}
static wxPen cordLine(wxColor(0,0,0),1);
static wxPen cordWget(wxColor(0,0,0),1);
static wxPen lineRed(wxColor(255,0,0),2);
static wxPen lineBlue(wxColor(0,0,255),2);
static wxPen label(wxColor(0,0,255),1);

static wxBrush back(wxColor(255,255,250));

static unsigned int \
			    titleH=30,
		    YLabelW=70,
		    widgBig=10,
		    widgSm=5
		    ;
		    static int smTextH=20;
		    static int cordLeft,
		    cordRight,
		    cordUp,
		    cordBottom;
static int cordW,cordH;

static const wxFont normalFont( 8, wxSWISS, wxNORMAL, wxNORMAL );


void chart::realDraw(wxDC&  dc)
{
	//调整所有字符串的像素
	/*
	   ------------------------------
	   |					1.					|
	   ------------------------------
	   |		|		| |
	   |		|		| |
	   |	2.	|	3.	| |			4.
	   |		|		| |
	   ------------------------------
	   ------------------------------
	   5.
	   ------------------------------
	   6.
	   ------------------------------
	   1.title
	   2.y label
	   3.y num label
	   4.cord
	   5.x num label
	   6.x label
	   */
	int ww,hh;
	this->GetSize(&ww,&hh);
	//背景
	dc.SetBrush(back);
	dc.DrawRectangle(0,0,ww,hh);


	//标题和标签
	//dc.SetBrush(*wxBLUE_BRUSH); // blue filling
	//   dc.SetPen( wxPen( wxColor(255,175,175), 10 ) ); // 10-pixels-thick pink outline
	//   dc.DrawRectangle( 300, 100, 400, 200 );
	dc.SetPen( label );
	dc.SetFont( wxFont( 18, wxSWISS, wxNORMAL, wxNORMAL ) );
	//dc.DrawText(title, 50, 20);
	dc.DrawLabel(title,wxRect(0,0,ww,titleH),wxALIGN_CENTER);
	dc.SetFont( normalFont );

	dc.DrawRotatedText(ylabel ,0 ,\
			hh/2+dc.GetTextExtent(ylabel).GetWidth()/2 , 90);
	dc.DrawText(xlabel, cordLeft+(cordW)/2-dc.GetTextExtent(xlabel).GetWidth()/2,\
			hh-dc.GetTextExtent(xlabel).GetHeight());

	//坐标轴
	dc.SetPen( cordLine );
	dc.DrawLine( cordLeft-widgBig, cordBottom, 
			cordRight,cordBottom);
	dc.DrawLine( cordLeft, cordUp,
			cordLeft, cordBottom+widgBig ); 

	//画标记和坐标值前先判断点的个数
	int sum_size=red.getSize()+blue.getSize();

	if(sum_size==0 )
	{
		//x	--->
		dc.DrawLine( cordLeft+(cordW)/2,  cordBottom, cordLeft+(cordW)/2, cordBottom+ widgBig);
		static const wxString NotAvail=L"N/A";
		wxSize sz=dc.GetTextExtent(NotAvail);
		dc.DrawText(NotAvail,  cordLeft+(cordW)/2-sz.GetWidth()/2, cordBottom+smTextH);
		//y	↓
		dc.DrawLine(cordLeft-widgBig, cordUp+(cordH)/2, cordLeft, cordUp+(cordH)/2);
		dc.DrawText(NotAvail, smTextH+30, cordUp+(cordH)/2-smTextH/2);
	}
	else if(sum_size==1)
	{
		//x
		dc.DrawLine( cordLeft+(cordW)/2,  cordBottom, cordLeft+(cordW)/2, cordBottom+ widgBig);
		wxString lab;
		lab.Printf(_T("      %6.2e"),(int)miny);
		wxSize sz=dc.GetTextExtent(lab);
		dc.DrawText(lab, cordLeft+(cordW)/2-sz.GetWidth()/2, cordBottom+smTextH);
		//y
		dc.DrawLine(cordLeft-widgBig, cordUp+(cordH)/2, cordLeft, cordUp+(cordH)/2);
		dc.DrawText(lab, smTextH, cordUp+(cordH)/2-smTextH/2);
	}
	else
	{
		wxString lab;
		wxSize sz;
		//x标记
		int start=cordLeft,index=0;
		while(start<=cordRight)
		{
			if(index==5 || index==0)
			{
				dc.DrawLine( start,  cordBottom, start, cordBottom+ widgBig);
				lab.Printf(_T("%d"),(int)(minx+(maxx-minx)*(start-cordLeft)/(cordRight-cordLeft)));
				sz=dc.GetTextExtent(lab);
				dc.DrawText(lab,start-sz.GetWidth()/2, cordBottom+smTextH);
				index=0;
			}
			else
			{
				dc.DrawLine( start,cordBottom, start, cordBottom+ widgSm );
			}
			index++;
			start+=24;
		}
		//y轴标记
		start=cordBottom;
		index=0;
		while(start>=cordUp)
		{
			if(index==5||index==0)
			{
				dc.DrawLine( cordLeft,  start, cordLeft-widgBig, start );
				lab.Printf(_T("      %6.2e"),miny+(maxy-miny)*(cordBottom-start)/(cordBottom-cordUp));
				sz=dc.GetTextExtent(lab);
				dc.DrawText(lab,smTextH,  start-smTextH/2);
				index=0;
			}
			else
			{
				dc.DrawLine( cordLeft, start, cordLeft-widgSm, start );
			}
			index++;
			start-=24;
		}

	}

	//再画曲线
	//直接将屏幕坐标画出
	//red和blue数目并不一样多
	dc.SetPen( lineRed );
	unsigned int size=virRed.size();
	for(unsigned int ii=0;ii<size;ii++)
	{
		if(ii!=size-1)
		{

			dc.DrawLine( virRed[ii]->x,  virRed[ii]->y,
					virRed[ii+1]->x,  virRed[ii+1]->y);
			//(wxT("ssasa"));lineBlue

		}
		else
			dc.DrawCircle(virRed[ii]->x,  virRed[ii]->y,3);
	}

	dc.SetPen( lineBlue );
	size=virBlue.size();
	for(unsigned int ii=0;ii<size;ii++)
	{
		if(ii!=size-1)
		{
			dc.DrawLine( virBlue[ii]->x,  virBlue[ii]->y,
					virBlue[ii+1]->x,  virBlue[ii+1]->y);

		}
		else
			dc.DrawCircle(virBlue[ii]->x,  virBlue[ii]->y,3);
	}
	//信息显示
	if(busy)
	{
		dc.SetPen( cordLine );
		dc.DrawText(L"正在平均并绘制图像...",0,hh-30);
	}

}
void chart::onSizeEvt(wxSizeEvent&WXUNUSED(e))
{
	refreshAll();
}
void chart::clearVir()
{
	for(unsigned int i=0;i<virRed.size();i++)
	{
		delete(virRed[i]);

	}
	virRed.clear();
	for(unsigned int i=0;i<virRed.size();i++)
	{
		delete(virBlue[i]);

	}
	virBlue.clear();
}
void chart::refreshAll()
{
	//将每个坐标转化为屏幕坐标
	//公式为 屏幕坐标x-50=(dx-minx)/(maxx-minx)*ww
	int ww,hh;
	this->GetSize(&ww,&hh);

	wxMemoryDC mdc;
	mdc.SetFont( normalFont );
	smTextH=mdc.GetTextExtent(L"text").GetHeight()+2;

	cordLeft=smTextH+YLabelW+widgBig;
	cordRight=ww-smTextH;
	cordUp=titleH;
	cordBottom=hh-2*smTextH-widgBig;

	cordW=cordRight-cordLeft;
	cordH=cordBottom-cordUp;

	//清除旧数据
	clearVir();

	unsigned int size=red.getSize();
	for(unsigned int ii=0;ii<size;ii++)
	{
		wxPoint* pp=new wxPoint();
		pp->x=(int)(cordLeft+(red.getx(ii)-minx)/(maxx-minx)*cordW);
		pp->y=(int)(cordUp+(maxy-red.gety(ii))/(maxy-miny)*cordH);
		virRed.push_back(pp);


	}

	size=blue.getSize();
	for(unsigned int ii=0;ii<size;ii++)
	{
		wxPoint* pp=new wxPoint();
		pp->x=(int)(cordLeft+(blue.getx(ii)-minx)/(maxx-minx)*cordW);
		pp->y=(int)(cordUp+(maxy-blue.gety(ii))/(maxy-miny)*cordH);
		virBlue.push_back(pp);
	}

	this->Refresh();
}

void chart::setData(std::vector<Point*>&data,bool isRed)
{
	if(isRed)
	{
		red.dline=data;
	}
	else
	{
		blue.dline=data;
	}
	refreshAll();
}

void chart::setData(std::vector<Point*>*dRed,std::vector<Point*>*dBlue)
{
	busy=true;
	this->Refresh();
	red.dline=*dRed;

	blue.dline=*dBlue;
	wxLogMessage(L"Curce size=%d,%d",red.dline.size(),blue.dline.size());
	//更新边界
	unsigned int redSize=red.dline.size(),
		     blueSize=blue.getSize();
	bool Inited=false;
	for(unsigned int i=0;i<redSize;i++)
	{
		if(i==0)
		{
			minx=red.dline[0]->x;
			maxx=red.dline[redSize-1]->x;
			maxy=miny=red.dline[0]->y;
			Inited=true;
		}

		if(red.dline[i]->y>maxy)
			maxy=red.dline[i]->y;
		if(red.dline[i]->y<miny)
			miny=red.dline[i]->y;
	}

	for(unsigned int i=0;i<blueSize;i++)
	{
		if(i==0 && !Inited)
		{
			minx=blue.dline[0]->x;
			maxx=blue.dline[blueSize-1]->x;
			maxy=miny=blue.dline[0]->y;
		}
		if(blue.dline[i]->y>maxy)
			maxy=blue.dline[i]->y;
		if(blue.dline[i]->y<miny)
			miny=blue.dline[i]->y;
	}

	refreshAll(); 
	busy=false;
}


